package com.lanchetech.bean.redission;

import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.RedissonLock;
import org.redisson.command.CommandAsyncExecutor;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * 分布式锁集合,现用redisson
 */
@Service
public class LockCenter implements ApplicationContextAware {

    private static final String DEFAULT_KEY = "DEFAULT_KEY";
    private static ApplicationContext applicationContext;
    private static Redisson redisson;

    public static Lock getLock() {
        return new VLock(getRedisson().getCommandExecutor(), DEFAULT_KEY);
    }

    public static Lock getLock(Class clazz) {
        if (clazz == null) return getLock();
        return getLock(clazz.getCanonicalName());
    }

    public static Lock getLock(String lockName) {
        if (StringUtils.isBlank(lockName)) {
            return getLock();
        }
        return new VLock(getRedisson().getCommandExecutor(), lockName);
    }

    private static Redisson getRedisson() {
        if (redisson == null) {
            // 根据方法名查找redisson  bean 的加载名称
            redisson = (Redisson) applicationContext.getBean("redisson");
        }
        return redisson;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        LockCenter.applicationContext = applicationContext;
    }

    static class VLock extends RedissonLock {

        VLock(CommandAsyncExecutor commandExecutor, String name) {
            super(commandExecutor, name);
        }

        @Override
        public void lock() {
            super.lock(1, TimeUnit.MINUTES);
        }

        @Override
        public void unlock() {
            try {
                if (isLocked()) {
                    super.unlock();
                }
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }
}
